#include "TcpClient.h"

using namespace std;

TcpClient::TcpClient()
{
	//ctor
	m_pBufRecv = new char[BUF_MAX_SIZE];  					// 接收缓冲区
	m_pBufSend = new char[BUF_MAX_SIZE]; 					// 发送缓冲区
}

TcpClient::~TcpClient()
{
	//dtor
	SAFE_DELETE_ARY(m_pBufRecv);
	SAFE_DELETE_ARY(m_pBufSend);
}

// 创建套接字地址结构
int TcpClient::Create()
{
	//cout << "==> call TcpClient::Create()." << endl;

	m_serverFd = socket(AF_INET, SOCK_STREAM, 0);
	if(-1 == m_serverFd)
	{
        //cout<< "==> TcpClient::Create() error when socket()"<<endl;
        Debug::Error("TcpClient::Create() error when socket()");
	}

	return m_serverFd;
}

// 绑定套接字地址
int TcpClient::Bind()
{
	//cout << "==> call TcpClient::Bind()." << endl;

	bzero(&m_ServerAddr, sizeof(m_ServerAddr));
	m_ServerAddr.sin_family 		= AF_INET;
	m_ServerAddr.sin_port 			= htons(m_serverPort);
	m_ServerAddr.sin_addr.s_addr 	= inet_addr(m_serverIp.c_str()); 		//  htonl();

	return 0;
}

// 初始化 _ip, 服务器IP， _port服务器程序端口号
int TcpClient::Init(string _ip, uint16_t _port)
{
	//cout << "==> call TcpClient::Init(). _ip:" << _ip<< ", port:"<< _port<<endl;

	m_serverIp		= _ip;
	m_serverPort 	= _port;

    this->Create();
    this->Bind();

	return 0;
}

// 链接服务器
int TcpClient::Connect()
{
	int ret = connect(m_serverFd, (struct sockaddr *)&m_ServerAddr,
					sizeof(m_ServerAddr));
	if(-1 == ret)
	{
		 //cout<< "==> TcpClient::Connect() error when connect(), comfirm the Server is Running"<<endl;
		 Debug::Error("TcpClient::Connect() error when connect(), comfirm the Server is Running");
		 return ret;
	}

	return 0;
}

// 收发循环
int TcpClient::RecvSendLoop()
{
	Debug::State("U connect sccessed. begin TcpClient::RecvSendLoop()");
	while(1)
	{
		size_t recvLen = (size_t)recv(m_serverFd, &m_pBufRecv[0], BUF_MAX_SIZE, 0);
		if(recvLen >= BUF_MAX_SIZE)
		{
			//std::cout<< "==>the msg len beyond limit: \t"<< BUF_MAX_SIZE<< endl;
			Debug::Error("The msg len beyond limit: \t", BUF_MAX_SIZE);
			continue;
		}
		else if(recvLen == 0)
		{
			// 如果等于0 关闭链接
			Close();
			return 0;
		}

		UnpackAndPushInQunue(recvLen);
	}

	return 0;
}

// 断开链接
int TcpClient::Close()
{
	shutdown(m_serverFd, SHUT_RDWR);
	Debug::State("Close TcpClient");
	return 0;
}

MsgQunue& TcpClient::GetMsgQunue(){
	return m_MsgQunue;
}

void TcpClient::UnpackAndPushInQunue(size_t _recvLen)
{
	/* 包描述 cmd + 内容 才是真真的消息
	-------------------------------------------------------------
	| 0x02 0x02 | len | cmd | ********内容********** | 0x03 0X03 |
	-------------------------------------------------------------
		  2B       4B    4B          len-8B              2B

	测试数据：02 02 31 30 30 32 30 32 48 65 6C 6C 6F 20 03 03 0D
	*/

	const size_t packetBeginLen = 2;
	const size_t packetEndLen = 2;
	const size_t lenLen = 4;

	const size_t contentLenLimit = MSG_LEN_MAX;

	const char packetBegin 	= '\2'; 		// 双左斜杠表示包开始
	const char packetEnd 	= '\3'; 		// 双右斜杠表示包结束
	size_t pos 	= 0;

	while(pos+4 < _recvLen) 				//	//判断 包是否已经读完
	{
		// 判断包头
		if((m_pBufRecv[pos] != packetBegin) || (m_pBufRecv[pos+1] != packetBegin)) 		// 开始符 2B
		{
			//std::cout<< "a bad package. begin error."<< endl;
			Debug::Error("TcpClient. A bad msg package. begin error.");
			return;
		}

		alen lensss;
		memcpy(lensss.a, &m_pBufRecv[pos + packetBeginLen], lenLen);
		int len = lensss.i;
		size_t msgTotalLen = len + packetBeginLen + packetEndLen;

		// 如果一个包长度大于contentLenLimit 就被认为是坏包被抛弃掉
		if(msgTotalLen > contentLenLimit)
		{
			Debug::Error("U got a bad package. len =", msgTotalLen, "beyond ", contentLenLimit);
			return;
		}

		char msgBuf[contentLenLimit] = {0};
		memcpy(msgBuf, &m_pBufRecv[pos], msgTotalLen);

		// 判断包尾
		pos += msgTotalLen - packetEndLen;
		int endIndex = pos;
		//cout<< "endIndex: "<< endIndex<<endl;

		if((m_pBufRecv[endIndex] == packetEnd) && (m_pBufRecv[endIndex+1] == packetEnd))
		{
			Message Msg(m_serverFd);
			Msg.Decode(msgBuf, msgTotalLen);

			m_MsgQunue.PushRecvMsg(Msg);
		}
		else
		{
			//std::cout<< "a bad package. end error.. len ="<< msgTotalLen<< endl;
			Debug::Error("A bad package. end error.. len =", msgTotalLen);
			return ;
		}

	}

}

void TcpClient::Send(Message* _pMsg)
{
	// YU_TODO: 是否需要单独开个线程来处理

	int sendLen = _pMsg->m_len + 4;
//	memset(&m_pBufSend[0], 0, sizeof(m_pBufSend)); 		// 发送缓冲区清空
//	memcpy(&m_pBufSend[0], _pMsg->GetBuf(), sendLen);

	send(m_serverFd, _pMsg->GetBuf(), sendLen, 0);

//	Debug::Log("Send a msg, fd:", _pMsg->m_fd, " \tcmd:", (int)_pMsg->m_cmd,
//				" \tlen:", _pMsg->m_len);
}

int TcpClient::GetFd()
{
	return m_serverFd;
}
